<template>
  <div class="max-w-4xl mx-auto p-4">
    <a-card>
      <a-typography-title :level="2">代码工具</a-typography-title>
      
      <a-tabs v-model:activeKey="activeTab">
        <!-- 代码格式化 -->
        <a-tab-pane key="formatter" tab="代码格式化">
          <a-form layout="vertical">
            <a-form-item label="语言">
              <a-select v-model:value="language">
                <a-select-option value="javascript">JavaScript</a-select-option>
                <a-select-option value="typescript">TypeScript</a-select-option>
                <a-select-option value="html">HTML</a-select-option>
                <a-select-option value="css">CSS</a-select-option>
                <a-select-option value="json">JSON</a-select-option>
                <a-select-option value="sql">SQL</a-select-option>
                <a-select-option value="xml">XML</a-select-option>
              </a-select>
            </a-form-item>

            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <div class="flex justify-between mb-2">
                  <span>输入代码</span>
                  <a-button type="link" size="small" @click="pasteCode">
                    粘贴
                  </a-button>
                </div>
                <a-textarea
                  v-model:value="inputCode"
                  :rows="15"
                  class="font-mono"
                  @keydown.tab.prevent="handleTab"
                />
              </div>

              <div>
                <div class="flex justify-between mb-2">
                  <span>格式化结果</span>
                  <a-button type="link" size="small" @click="copyResult">
                    复制
                  </a-button>
                </div>
                <div class="relative">
                  <pre class="language-auto"><code v-html="highlightedCode"></code></pre>
                </div>
              </div>
            </div>

            <a-form-item>
              <a-space>
                <a-button type="primary" @click="formatCode">
                  格式化
                </a-button>
                <a-button @click="minifyCode">
                  压缩
                </a-button>
                <a-button @click="clearCode">
                  清空
                </a-button>
              </a-space>
            </a-form-item>

            <a-form-item label="格式化选项">
              <a-space direction="vertical">
                <a-checkbox v-model:checked="formatOptions.semicolons">
                  添加分号
                </a-checkbox>
                <a-checkbox v-model:checked="formatOptions.singleQuotes">
                  使用单引号
                </a-checkbox>
                <a-checkbox v-model:checked="formatOptions.trailingCommas">
                  尾随逗号
                </a-checkbox>
                <div class="flex items-center gap-2">
                  <span>缩进空格数：</span>
                  <a-input-number
                    v-model:value="formatOptions.tabWidth"
                    :min="2"
                    :max="8"
                    :step="2"
                  />
                </div>
              </a-space>
            </a-form-item>
          </a-form>
        </a-tab-pane>

        <!-- CSS 前缀生成器 -->
        <a-tab-pane key="css-prefixer" tab="CSS 前缀生成器">
          <a-form layout="vertical">
            <a-form-item label="输入 CSS">
              <a-textarea
                v-model:value="cssInput"
                :rows="10"
                class="font-mono"
                placeholder="例如：
transform: rotate(45deg);
user-select: none;
backdrop-filter: blur(10px);"
              />
            </a-form-item>

            <a-form-item>
              <a-space>
                <a-button type="primary" @click="addPrefixes">
                  添加前缀
                </a-button>
                <a-button @click="clearCss">
                  清空
                </a-button>
                <a-button @click="copyCss">
                  复制结果
                </a-button>
              </a-space>
            </a-form-item>

            <a-form-item label="生成结果">
              <pre class="language-css"><code v-html="highlightedCss"></code></pre>
            </a-form-item>

            <a-form-item label="浏览器支持">
              <a-checkbox-group v-model:value="browsers">
                <a-checkbox value="chrome">Chrome</a-checkbox>
                <a-checkbox value="firefox">Firefox</a-checkbox>
                <a-checkbox value="safari">Safari</a-checkbox>
                <a-checkbox value="opera">Opera</a-checkbox>
                <a-checkbox value="ie">IE</a-checkbox>
              </a-checkbox-group>
            </a-form-item>
          </a-form>
        </a-tab-pane>

        <!-- JSON/XML 转换器 -->
        <a-tab-pane key="converter" tab="数据格式转换">
          <a-form layout="vertical">
            <a-form-item label="转换类型">
              <a-radio-group v-model:value="convertType" button-style="solid">
                <a-radio-button value="json2xml">JSON → XML</a-radio-button>
                <a-radio-button value="xml2json">XML → JSON</a-radio-button>
                <a-radio-button value="json2csv">JSON → CSV</a-radio-button>
                <a-radio-button value="csv2json">CSV → JSON</a-radio-button>
              </a-radio-group>
            </a-form-item>

            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
              <div>
                <div class="flex justify-between mb-2">
                  <span>输入</span>
                  <a-space>
                    <a-button type="link" size="small" @click="validateInput">
                      验证
                    </a-button>
                    <a-button type="link" size="small" @click="formatInput">
                      格式化
                    </a-button>
                  </a-space>
                </div>
                <a-textarea
                  v-model:value="convertInput"
                  :rows="15"
                  class="font-mono"
                />
              </div>

              <div>
                <div class="flex justify-between mb-2">
                  <span>输出</span>
                  <a-button type="link" size="small" @click="copyConverted">
                    复制
                  </a-button>
                </div>
                <pre class="language-auto"><code v-html="highlightedConverted"></code></pre>
              </div>
            </div>

            <a-form-item>
              <a-space>
                <a-button type="primary" @click="convert">
                  转换
                </a-button>
                <a-button @click="clearConvert">
                  清空
                </a-button>
              </a-space>
            </a-form-item>
          </a-form>
        </a-tab-pane>
      </a-tabs>
    </a-card>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, nextTick } from 'vue';
import { message } from 'ant-design-vue';
import prettier from 'prettier';
import babel from '@babel/plugin-syntax-jsx';
import typescript from '@babel/preset-typescript';
import organizeImports from 'prettier-plugin-organize-imports';
import xmlPlugin from '@prettier/plugin-xml';
import sqlPlugin from 'prettier-plugin-sql';
import hljs from 'highlight.js';
import autoprefixer from 'autoprefixer';
import postcss from 'postcss';
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
import Papa from 'papaparse';

// 标签页
const activeTab = ref('formatter');

// 代码格式化
const language = ref('javascript');
const inputCode = ref('');
const formatOptions = ref({
  semicolons: true,
  singleQuotes: true,
  trailingCommas: true,
  tabWidth: 2
});

// 格式化代码
const formatCode = async () => {
  try {
    let formatted = '';
    const options = {
      semi: formatOptions.value.semicolons,
      singleQuote: formatOptions.value.singleQuotes,
      trailingComma: formatOptions.value.trailingCommas ? 'all' as const : 'none' as const,
      tabWidth: formatOptions.value.tabWidth,
      parser: language.value === 'typescript' ? 'babel-ts' : language.value,
      plugins: [babel, typescript, organizeImports, xmlPlugin, sqlPlugin]
    };

    switch (language.value) {
      case 'javascript':
      case 'typescript':
        formatted = await prettier.format(inputCode.value, options);
        break;
      case 'html':
        formatted = await prettier.format(inputCode.value, { ...options, parser: 'html' });
        break;
      case 'css':
        formatted = await prettier.format(inputCode.value, { ...options, parser: 'css' });
        break;
      case 'json':
        formatted = await prettier.format(inputCode.value, { ...options, parser: 'json' });
        break;
      case 'sql':
        formatted = await prettier.format(inputCode.value, { ...options, parser: 'sql' });
        break;
      case 'xml':
        formatted = await prettier.format(inputCode.value, { ...options, parser: 'xml' });
        break;
    }

    inputCode.value = formatted;
    message.success('格式化成功');
  } catch (e) {
    message.error('格式化失败：' + (e as Error).message);
    console.error('格式化失败:', e);
  }
};

// 压缩代码
const minifyCode = async () => {
  try {
    let minified = '';
    const options = {
      semi: true,
      printWidth: Infinity,
      plugins: [babel, typescript, organizeImports, xmlPlugin, sqlPlugin]
    };

    switch (language.value) {
      case 'javascript':
      case 'typescript':
        minified = await prettier.format(inputCode.value, {
          ...options,
          parser: language.value === 'typescript' ? 'babel-ts' : 'babel'
        });
        break;
      case 'html':
      case 'xml':
        minified = await prettier.format(inputCode.value, {
          ...options,
          parser: language.value === 'xml' ? 'xml' : 'html'
        });
        break;
      case 'css':
        minified = await prettier.format(inputCode.value, {
          ...options,
          parser: 'css'
        });
        break;
      case 'json':
        minified = await prettier.format(inputCode.value, {
          ...options,
          parser: 'json'
        });
        break;
      case 'sql':
        minified = await prettier.format(inputCode.value, {
          ...options,
          parser: 'sql'
        });
        break;
    }

    inputCode.value = minified;
    message.success('压缩成功');
  } catch (e) {
    message.error('压缩失败：' + (e as Error).message);
    console.error('压缩失败:', e);
  }
};

// 语法高亮
const highlightedCode = computed(() => {
  if (!inputCode.value) return '';
  try {
    const highlighted = hljs.highlight(inputCode.value, {
      language: language.value
    }).value;
    return highlighted;
  } catch (e) {
    console.error('高亮失败:', e);
    return inputCode.value;
  }
});

// CSS 前缀生成器
const cssInput = ref('');
const browsers = ref(['chrome', 'firefox', 'safari']);

// 添加 CSS 前缀
const addPrefixes = async () => {
  try {
    const browserList = browsers.value.map(browser => {
      switch (browser) {
        case 'chrome': return 'last 2 Chrome versions';
        case 'firefox': return 'last 2 Firefox versions';
        case 'safari': return 'last 2 Safari versions';
        case 'opera': return 'last 2 Opera versions';
        case 'ie': return 'IE >= 11';
        default: return '';
      }
    }).filter(Boolean);

    const prefixer = postcss([
      autoprefixer({
        overrideBrowserslist: browserList
      })
    ]);

    const result = await prefixer.process(cssInput.value, { from: undefined });
    cssInput.value = result.css;
    message.success('添加前缀成功');
  } catch (e) {
    message.error('添加前缀失败：' + (e as Error).message);
    console.error('添加前缀失败:', e);
  }
};

// CSS 语法高亮
const highlightedCss = computed(() => {
  if (!cssInput.value) return '';
  try {
    return hljs.highlight(cssInput.value, { language: 'css' }).value;
  } catch (e) {
    console.error('高亮失败:', e);
    return cssInput.value;
  }
});

// 数据格式转换
const convertType = ref('json2xml');
const convertInput = ref('');
const convertOutput = ref('');

// 转换格式
const convert = () => {
  try {
    switch (convertType.value) {
      case 'json2xml': {
        const json = JSON.parse(convertInput.value);
        const builder = new XMLBuilder();
        convertOutput.value = builder.build(json);
        break;
      }
      case 'xml2json': {
        const parser = new XMLParser();
        const json = parser.parse(convertInput.value);
        convertOutput.value = JSON.stringify(json, null, 2);
        break;
      }
      case 'json2csv': {
        const json = JSON.parse(convertInput.value);
        if (!Array.isArray(json)) {
          throw new Error('JSON 必须是数组格式');
        }
        convertOutput.value = Papa.unparse(json);
        break;
      }
      case 'csv2json': {
        const result = Papa.parse(convertInput.value, { header: true });
        convertOutput.value = JSON.stringify(result.data, null, 2);
        break;
      }
    }
    message.success('转换成功');
  } catch (e) {
    message.error('转换失败：' + (e as Error).message);
    console.error('转换失败:', e);
  }
};

// 验证输入
const validateInput = () => {
  try {
    switch (convertType.value) {
      case 'json2xml':
      case 'json2csv':
        JSON.parse(convertInput.value);
        break;
      case 'xml2json':
        new XMLParser().parse(convertInput.value);
        break;
      case 'csv2json':
        Papa.parse(convertInput.value, { header: true });
        break;
    }
    message.success('验证通过');
  } catch (e) {
    message.error('验证失败：' + (e as Error).message);
  }
};

// 格式化输入
const formatInput = () => {
  try {
    const options = {
      semi: true,
      tabWidth: 2,
      plugins: [babel, typescript, organizeImports, xmlPlugin, sqlPlugin]
    };

    switch (convertType.value) {
      case 'json2xml':
      case 'json2csv':
        convertInput.value = JSON.stringify(JSON.parse(convertInput.value), null, 2);
        break;
      case 'xml2json':
        prettier.format(convertInput.value, {
          ...options,
          parser: 'xml'
        }).then(formatted => {
          convertInput.value = formatted;
        });
        break;
      case 'csv2json':
        // CSV 格式化暂不支持
        break;
    }
    message.success('格式化成功');
  } catch (e) {
    message.error('格式化失败：' + (e as Error).message);
  }
};

// 高亮转换结果
const highlightedConverted = computed(() => {
  if (!convertOutput.value) return '';
  try {
    const language = convertType.value.endsWith('json') ? 'json' :
      convertType.value.endsWith('xml') ? 'xml' : 'csv';
    return hljs.highlight(convertOutput.value, { language }).value;
  } catch (e) {
    console.error('高亮失败:', e);
    return convertOutput.value;
  }
});

// 辅助函数
const handleTab = (e: KeyboardEvent) => {
  const target = e.target as HTMLTextAreaElement;
  const start = target.selectionStart;
  const end = target.selectionEnd;
  const spaces = ' '.repeat(formatOptions.value.tabWidth);
  
  inputCode.value = inputCode.value.substring(0, start) + spaces + inputCode.value.substring(end);
  
  // 保持光标位置
  nextTick(() => {
    target.selectionStart = target.selectionEnd = start + formatOptions.value.tabWidth;
  });
};

const clearCode = () => {
  inputCode.value = '';
  message.success('已清空');
};

const clearCss = () => {
  cssInput.value = '';
  message.success('已清空');
};

const clearConvert = () => {
  convertInput.value = '';
  convertOutput.value = '';
  message.success('已清空');
};

const copyResult = async () => {
  try {
    await navigator.clipboard.writeText(inputCode.value);
    message.success('已复制到剪贴板');
  } catch (e) {
    message.error('复制失败');
  }
};

const copyCss = async () => {
  try {
    await navigator.clipboard.writeText(cssInput.value);
    message.success('已复制到剪贴板');
  } catch (e) {
    message.error('复制失败');
  }
};

const copyConverted = async () => {
  try {
    await navigator.clipboard.writeText(convertOutput.value);
    message.success('已复制到剪贴板');
  } catch (e) {
    message.error('复制失败');
  }
};

const pasteCode = async () => {
  try {
    const text = await navigator.clipboard.readText();
    inputCode.value = text;
    message.success('已粘贴');
  } catch (e) {
    message.error('粘贴失败');
  }
};
</script>

<style scoped>
:deep(pre) {
  margin: 0;
  padding: 1rem;
  border-radius: 4px;
  background-color: #f5f5f5;
  overflow-x: auto;
}

:deep(code) {
  font-family: Menlo, Monaco, Consolas, monospace;
  font-size: 0.875rem;
  line-height: 1.5;
}

.ant-form-item {
  margin-bottom: 1rem;
}
</style> 